package com.droid.mvvmlib.base;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.droid.framwork.ui.BaseFragment;
import com.droid.mvvmlib.log.Logcat;
import com.droid.mvvmlib.router.RouterProxy;
import com.droid.mvvmlib.utils.ProcessUtil;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.Observer;

/**
 * 基类 Fragment
 *
 * @author zyc0617
 * @since  2019/7/5 16:27
 */
public abstract class SuperBaseFragment<V extends ViewDataBinding, VM extends UiChangeViewModel, M extends BaseModel, D>
        extends BaseFragment implements IBaseView, Observer {

    protected UiChangeViewModel uiChangeViewModel;
    protected Activity mActivity;
    protected V viewDataBinding;
    protected VM viewModel;

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        mActivity = getActivity();
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onCreate");
        initParam();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onCreateView");
        viewDataBinding =  DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
        return viewDataBinding.getRoot();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onViewCreated");
        viewModel = getViewModel();
        if (viewModel != null) {
            getLifecycle().addObserver(viewModel);
        }
        performDataBinding();
        initViewModels();
        initViewObservable();
        initData();

        initUiChangeLiveDataCallBack(viewModel);
    }

    private void performDataBinding(){
        viewDataBinding.setLifecycleOwner(this);
        this.viewModel = viewModel == null ? getViewModel() : viewModel;
        if (getBindingVariableId() > 0) {
            viewDataBinding.setVariable(getBindingVariableId(), viewModel);
        }
        viewDataBinding.executePendingBindings();
    }

    @Override
    public void onResume() {
        super.onResume();
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onResume");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onDestroy");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Logcat.d(getFragmentTag(), "Activity:"+mActivity+" Fragment:"+getFragmentTag()+" onDestroyView");
    }

    /**
     * 注册ViewModel与View的契约UI回调事件
     * @param viewModel
     */
    protected void initUiChangeLiveDataCallBack(@NonNull UiChangeViewModel viewModel) {
        viewModel.getUiChangeLiveData().getShowDialogEvent().observe(this, dialog -> {
            if (dialog != null) {
                dialog.show(mActivity);
            }
        });

        viewModel.getUiChangeLiveData().getDismissDialogEvent().observe(this, dialog -> {
            if (dialog != null) {
                dialog.dismiss();
            }
        });

        viewModel.getUiChangeLiveData().getStartActivityEvent().observe(this, params -> {
            if (params == null) {
                Logcat.e(getFragmentTag(), "getStartActivityEvent params is null!");
                return;
            }

            startActivity(params);
        });

        viewModel.getUiChangeLiveData().getFinishAndExitApplicationEvent().observe(this, aBoolean -> exitApplication());

        viewModel.getUiChangeLiveData().getFinishActivityEvent().observe(this, intent -> {
            Logcat.i(getFragmentTag(), "finishActivity: " + mActivity.getClass().getSimpleName());
            if (intent == null) {
                mActivity.finish();
            } else {
                mActivity.setResult(Activity.RESULT_OK, intent);
                mActivity.finish();
            }
        });
    }

    private void startActivity(UiChangeViewModel.StartActivityParams params) {
        RouterProxy.getInstance().startActivity(mActivity, params.getPath(), params.getBundle(), params.getFlag(), params.getCallback(), params.getReqCode());
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        Logcat.i(getFragmentTag(), "enter onActivityResult");
        super.onActivityResult(requestCode, resultCode, data);
    }

    protected void exitApplication() {
        if (mActivity == null) {
            Logcat.w(getFragmentTag(), "mActivity is null");
            return;
        }
        mActivity.finish();
        ProcessUtil.killSelfDelay();
    }

    protected abstract int getBindingVariableId();

    @LayoutRes
    protected abstract int getLayoutId();

    protected abstract void onRetryBtnClick();

    protected abstract VM getViewModel();

    protected abstract String getFragmentTag();

    protected abstract void onListItemInsert(ObservableArrayList<D> sender, int positionStart, int itemCount);

    private BaseOnListenerCallBack<D> onListChangeCallBack = new BaseOnListenerCallBack<D>() {
        @Override
        protected void onItemInsert(ObservableArrayList<D> sender, int positionStart, int itemCount) {
            onListItemInsert(sender, positionStart, itemCount);
        }
    };

    @Override
    public void initParam() {

    }

    @Override
    public void initData() {

    }

    @Override
    public void requestPermission() {

    }

    @Override
    public void initViewObservable() {
        if (viewModel instanceof BaseNonPagingViewModel) {
            ((ObservableArrayList) ((BaseNonPagingViewModel) viewModel).dataList.getValue()).addOnListChangedCallback(onListChangeCallBack);
        }

        if (viewModel instanceof BasePagingViewModel) {
            ((ObservableArrayList) ((BasePagingViewModel) viewModel).dataList.getValue()).addOnListChangedCallback(onListChangeCallBack);
        }
        viewModel.viewStatus.observe(this, this);
    }

    @Override
    public void initViewModels() {

    }

    public abstract void onTryRefresh();
}
